#ifndef __SESSION_HPP_
#define __SESSION_HPP_

#include <boost/asio.hpp>
#include <boost/array.hpp>
#include <boost/shared_ptr.hpp>

#include <string>
#include <iostream>
//#include "../../utils/others/aesfast.hpp"

#define SB_BUF_MAX	1024


    namespace network
    {

#define SEND( packet, class_handle )		m_socket.async_write_some( packet, boost::bind( &class_handle::handle_write, shared_from_this(), boost::asio::placeholders::error,boost:asio::placeholders::bytes_transferred))
#define CRYPTNSEND( packet , class_handle)	m_socket.async_write_some(crypt.aes_crypt(packet),											\
																		  boost::bind(&class_handle::handle_write, shared_from_this(),		\
																					  boost::asio::placeholders::error,						\
																					  boost::asio::placeholders::bytes_transferred))


        namespace packet
        {
            class CancelOperation;
			class RequestGeneriks;
		}

        namespace buffer
        {
            class BasicBuffer;
        }

        class Session
        {
        public:

            explicit Session(boost::asio::io_service& _ioService);

            /**
             * Start the session with the first asynchronous operation
             */
            virtual void start() = 0;

            /**
             * Stop all asynchronous operations running linked to this session
             */
            virtual void stop();


            /**
             * Getter to the pointer of the socket communicating with the client
             * @return pointer of the socket communicating with the client
             */
            boost::asio::ip::tcp::socket& socket();


            virtual void on_packet(buffer::BasicBuffer& _packet) = 0;
			virtual void on_packet(packet::CancelOperation& _packet);
			virtual void on_packet(packet::RequestGeneriks& _packet){}

            virtual ~Session()
            {
            }

            /**
             * Crypto object commom to all sessions for the crypto of the first packet
             */
            //static utils::WeaselCrypt& first_packet_crypt();


        protected:

            /**
             * Session's socket
             */
            boost::asio::ip::tcp::socket m_socket;

			/**
             * Function called when new data arrived on the buffer
             */
            virtual void handle_read_first_packet(const boost::system::error_code& e, std::size_t bytes_transferred) = 0;

            /**
             * Function called when new data arrived on the buffer
             */
            virtual void handle_read(const boost::system::error_code& e, std::size_t bytes_transferred) = 0;


            /**
             * Function called after write on the socket, we get the state
             */
            virtual void handle_write(const boost::system::error_code& e, std::size_t bytes_transferred) = 0;





            /**
             * Reading buffer on input packets
             */
            //boost::array<char,1024> read_buffer_;
            //char buff_[1024];

            boost::shared_ptr< std::vector<unsigned char> > m_read_buffer;
            std::size_t m_read_size;


            /**
             * Object that allows to activate crypto on the connexion
             */
            //utils::WeaselCrypt crypt;



        };

        typedef boost::shared_ptr<Session> session_ptr;

    } //  // namespace network

#endif // __SESSION_HPP_
